package ar.edu.utn.frsf.tpae.a2012.g03.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.Vector;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;

import ar.edu.utn.frsf.tpae.a2012.g03.dao.CuentasDAO;
import ar.edu.utn.frsf.tpae.a2012.g03.model.CajaAhorro;
import ar.edu.utn.frsf.tpae.a2012.g03.model.Cliente;
import ar.edu.utn.frsf.tpae.a2012.g03.model.Cuenta;
import ar.edu.utn.frsf.tpae.a2012.g03.model.CuentaCorriente;

public class CuentasHibernateDAO implements CuentasDAO {

	private SessionFactory sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory();
	
	@Override
	public void listarCuentas() {
	    Session session = sessionFactory.openSession();
	    Query query = session.createQuery("from " + Cuenta.class.getName());

	    Vector<Cuenta> cuentas = (Vector<Cuenta>) query.list();
	    session.close();
	    for(Cuenta unaCuenta : cuentas) {
	    	System.out.println(unaCuenta);
	    }
	}

	@Override
	public void crearCuenta(Cuenta unaCuenta) throws Exception {
		Session session = sessionFactory.openSession();
		session.beginTransaction();
		if(unaCuenta.getCtaId() < 1)
			throw new Exception("Cuenta con id negativo");
		ArrayList<Cuenta> cuentasCreadas = getCuentas();
		for(Cuenta cta : cuentasCreadas)
			if(cta.getCtaNro() == unaCuenta.getCtaNro())
				throw new Exception("Cuenta ya existente");
		session.persist(unaCuenta);
		session.getTransaction().commit();
		session.close();
	}

	@Override
	public void modificarCuenta(Cuenta unaCuenta) {
		Session session = sessionFactory.openSession();
		session.beginTransaction();
		session.saveOrUpdate(unaCuenta);
		session.getTransaction().commit();
		session.close();
	}

	@Override
	public void borrarCuenta(Cuenta unaCuenta) {
		Session session = sessionFactory.openSession();
		session.beginTransaction();
		session.delete(unaCuenta);
		session.getTransaction().commit();
		session.close();
	}

	@Override
	public void listarClientes() {
	    Session session = sessionFactory.openSession();
	    Query query = session.createQuery("from " + Cliente.class.getName());

	    ArrayList<Cliente> clientes = (ArrayList<Cliente>) query.list();

	    for(Cliente unaCuenta : clientes) {
	    	System.out.println(unaCuenta);
	    }
	}

	@Override
	public void altaCliente(Cliente unCliente) throws Exception {
		Session session = sessionFactory.openSession();
		session.beginTransaction();
		session.persist(unCliente);
		session.getTransaction().commit();
		session.close();
	}

	@Override
	public void modificarCliente(Cliente unCliente) {
		Session session = sessionFactory.openSession();
		session.beginTransaction();
		session.update(unCliente);
		session.getTransaction().commit();
		session.close();
	}

	@Override
	public void eliminarCliente(Cliente unCliente) {
		Session session = sessionFactory.openSession();
		session.beginTransaction();
		session.delete(unCliente);
		session.getTransaction().commit();
		session.close();
	}

	@Override
	public int getCantidadCuentas() {
		Session session = null;
		List<Cuenta> cuentas = new ArrayList<Cuenta>();
		try{
			 session = sessionFactory.openSession();
			 Query query = session.createQuery("from " + Cuenta.class.getName());

			 cuentas = (List<Cuenta>) query.list();
		}
		catch (Exception ex) {
			ex.printStackTrace();
		}
		
		return cuentas.size();
	}
	
	@Override
	public int getCantidadClientes() {
		Session session = null;
		List<Cliente> clientes = new ArrayList<Cliente>();
		try{
			 session = sessionFactory.openSession();
			 Query query = session.createQuery("from " + Cliente.class.getName());

			 clientes = (List<Cliente>) query.list();
		}
		catch (Exception ex) {
			ex.printStackTrace();
		}
		
		return clientes.size();
	}

	@Override
	public int getCantidadCjaAho() {
		Session session = null;
		List<Cuenta> cuentas = new ArrayList<Cuenta>();
		try{
			session = sessionFactory.openSession();
			Query query = session.createQuery("from " + CajaAhorro.class.getName());

			cuentas = (List<Cuenta>) query.list();
		}
		catch (Exception ex) {
			ex.printStackTrace();
		}
		/*finally {
			if(session != null)
				session.close();
		}*/
		
		return cuentas.size();
	}

	@Override
	public int getCantidadCtaCte() {
		Session session = null;
		List<Cuenta> cuentas = new ArrayList<Cuenta>();
		try{
			session = sessionFactory.openSession();
			Query query = session.createQuery("from " + CuentaCorriente.class.getName());

			cuentas = (List<Cuenta>) query.list();
		}
		catch (Exception ex) {
			ex.printStackTrace();
		}
		/*finally {
			if(session != null)
				session.close();
		}*/
		
		return cuentas.size();
	}

	@SuppressWarnings("finally")
	@Override
	public Cuenta getCuenta(int id) {
		Cuenta cuentaDevuelta = null;
		Session session = null;
		try{
		session = sessionFactory.openSession();
		Query query = session.createQuery("from cuenta where ctaId = " + id);
		cuentaDevuelta = (Cuenta) query.uniqueResult();
		session.getTransaction().commit();	
		} catch(Exception ex) {
			throw new Exception("Error inesperado al obtener la cuenta. Probablemente el servidor no se encuentre disponible.");
		}
		finally {
			if(session != null) {
				session.close();
			}
			return cuentaDevuelta;
		}
	}
	
	@SuppressWarnings("finally")
	public Cliente getCliente(int id) {
	    Session session = sessionFactory.openSession();
	    return (Cliente) session.get(Cliente.class, id);
	}
	
	@SuppressWarnings({ "unchecked", "finally" })
	private ArrayList<Cuenta> getCuentas() {
		ArrayList<Cuenta> cuentas = null;
		Session session = null;
		try{
		session = sessionFactory.openSession();
		Query query = session.createQuery("from Cuenta");
		cuentas = (ArrayList<Cuenta>) query.list();
		session.getTransaction().commit();	
		} catch(Exception ex) {
			throw new Exception("Error inesperado al obtener cuentas. Probablemente el servidor no se encuentre disponible.");
		}
		finally {
			if(session != null) {
				session.close();
			}
			return cuentas;
		}
	}

}
